#include "teclado.h"
#include "println.h"
#include "io.h"

char scancodeTable[_NSC] = {
	/*make value for letters from a to z (break value is make value plus 0x80):*/ 
	0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22, 0x23, 0x17, 
	0x24, 0x25, 0x26, 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 
	0x1f, 0x14, 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c,
	/*make value for numbers from 0 to 9 (break value is make value plus 0x80):*/ 
	0x0b, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,	
	0x1c, //enter
	0x39 //space bar  	
};
char asciiTable[_NSC] = {
	/*ASCII value for letters from a to z:*/
	 97,  98,  99, 100, 101, 102, 103, 104, 105,
	106, 107, 108, 109, 110, 111, 112, 113, 114,
	115, 116, 117, 118, 119, 120, 121, 122,
	/*make value for numbers from 0 to 9 (break value is make value plus 0x80):*/
	 48,  49,  50,  51,  52,  53,  54,  55,  56,  57,
	_NEWLINE,/*line feed (newline) - It is the pair of the enter scan code*/
	_SPACE /*space*/
};

char asciiUpperTable[_NSC] = {
	/*ASCII value for letters from a to z:*/
	 65,  66, 67, 68, 69, 70, 71, 72, 73,
	74, 75, 76, 77, 78, 79, 80, 81, 82,
	83, 84, 85, 86, 87, 88, 89, 90,
	/*make value for numbers from 0 to 9 (break value is make value plus 0x80):*/
	 48,  49,  50,  51,  52,  53,  54,  55,  56,  57,
	_NEWLINE,/*line feed (newline) - It is the pair of the enter scan code*/
	_SPACE /*space*/
};

char kbBuffer[_KBBUFMAXSIZE];
int kbBufPos=0; /*The keyboard buffer is a circular list, this stores the current
initial position of the circular list*/
int kbBufSize=0; /*number of elements in the keyboard buffer*/
int enterPos=-1; /*position of the fisrt newline in the buffer, shall be
less than 0 if there is no newline*/
/*State of caps lock button.*/
int caps_state = 0;

char convSCtoASCII(char scancode){
	int i;
	for(i=0;i<_NSC;i++){
		if(scancode == scancodeTable[i])
			return(asciiTable[i]);	
	}	
	return(0);
}

char convSCtoUpperASCII(char scancode){
	int i;
	for(i=0;i<_NSC;i++){
		if(scancode == scancodeTable[i])
			return(asciiUpperTable[i]);	
	}	
	return(0);
}

void updateKbBuffer(char c){
	if(c>0){
		if(kbBufSize == _KBBUFMAXSIZE)
			kbBufPos = (kbBufPos+1)%_KBBUFMAXSIZE;		
		else
			kbBufSize++;
	
		kbBuffer[(kbBufPos+kbBufSize-1)%_KBBUFMAXSIZE] = c;
		
		if(c==_NEWLINE && enterPos<0)
			enterPos = kbBufPos+kbBufSize-1;
	}
}

void isr_irq1(unsigned long int erro){
	char scancode,t[2];
	scancode = inb(0x60); /* read from port 0x60 (8052, the ps2 keyboard controller)*/	
	if(scancode == 0x3a){
		if(caps_state == 0)
			caps_state = 1;
		else
			caps_state = 0;
	} else {
		if(caps_state == 0)
			t[0] = convSCtoASCII(scancode);
		else
			t[0] = convSCtoUpperASCII(scancode);
		t[1] = 0;
		updateKbBuffer(t[0]);
		if(t[0]!=_NEWLINE)
			print(t);
	}
}

void readLine(char *line){
/*line must be a char[] with enough space to store the line, that will have
at most _MAXKBBUFSIZE characters*/
	
	int i,z=0;		
		
	while(enterPos < 0){}/*wait for at least one line*/

	/*read a line from the buffer and copy to line*/
	for(i=kbBufPos;kbBuffer[i]!=_NEWLINE;i=(i+1)%_KBBUFMAXSIZE){
		line[z++] = kbBuffer[i];
		kbBufSize--;			
	}		
	line[z] = 0;
	kbBufSize--;
	kbBufPos = (i+1)%_KBBUFMAXSIZE;
	
	/*recalculate enterPos*/
	for(i=kbBufPos;kbBuffer[i]!=_NEWLINE && i!=((kbBufPos+kbBufSize)%_KBBUFMAXSIZE);i=(i+1)%_KBBUFMAXSIZE){}
	if(kbBuffer[i]==_NEWLINE)
		enterPos = i;
	else
		enterPos = -1;	
		
}

/*Controls the keyboard leds*/
void keyb_leds(unsigned char status){
	while((inb(0x64)&2)!=0){}
	outb(0x60,0xED);
	
	while((inb(0x64)&2)!=0){}
	outb(0x60,status);
}

